package com.clp.protocol.iec104.apdu.asdu.infoobj.infoelem.filetransfer;

import com.clp.protocol.iec104.apdu.asdu.infoobj.infoelem.filetransfer.dtfile.DTFile;
import com.clp.protocol.iec104.definition.ConstVal;
import com.clp.protocol.iec104.definition.Ft;
import com.clp.protocol.core.utils.ByteUtil;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 文件目录召唤确认 附加数据包
 */
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class FileReadDireConAttachPack extends AttachPack {
    @Override
    public Ft.OperationTag operationTag() {
        return Ft.OperationTag.FILE_READ_DIRE_CON;
    }

    /**
     * 结果描述字
     */
    private Ft.FileReadDireConRD fileReadDireConRD;

    /**
     * 目录id
     */
    private long direId;

    /**
     * 后续标志
     */
    private Ft.FollowUpFlag followUpFlag;

    /**
     * 本帧文件数量
     */
    private int fileNum;

    /**
     * 传输的文件列表
     */
    private List<DTFile> dtFiles;

    @Override
    public FileReadDireConAttachPack refreshFrom(ByteBuf buf) {
        checkOperationTag(buf.readByte());
        // 结果描述字
        this.fileReadDireConRD = Ft.FileReadDireConRD.gain(buf.readByte() & 0xFF);
        // 目录id
        byte[] direIdBytes = new byte[ConstVal.DIRE_ID_LEN]; buf.readBytes(direIdBytes);
        this.direId = ByteUtil.bytes4ToLongLE(direIdBytes);
        // 后续标志
        this.followUpFlag = Ft.FollowUpFlag.gain(buf.readByte() & 0xFF);
        // 文件数量
        this.fileNum = buf.readByte() & 0xFF;
        // 文件列表
        this.dtFiles = new ArrayList<>();
        for (int i = 0; i < fileNum; i++) {
            dtFiles.add(new DTFile().refreshFrom(buf));
        }
        return this;
    }

    @Override
    public boolean isValid() {
        if (fileReadDireConRD == null) return false;
        if (direId < 0 || direId > 0xFFFFFFFFL) return false;
        if (followUpFlag == null) return false;
        if (fileNum < 0 || fileNum > 0xFF) return false;
        if (dtFiles == null) return false;
        for (DTFile dtFile : dtFiles) {
            if (!dtFile.isValid()) {
                return false;
            }
        }
        return true;
    }

    @Override
    public void writeBytesTo(ByteBuf buf) {
        // 填写操作标识
        buf.writeByte(operationTag().getVal());
        // 结果描述字
        buf.writeByte(fileReadDireConRD.getVal());
        // 目录id
        buf.writeBytes(ByteUtil.longToBytes4LE(direId));
        // 后续标志
        buf.writeByte(followUpFlag.getVal());
        // 文件数量
        buf.writeByte(dtFiles.size());
        // 文件列表
        for (DTFile dtFile : dtFiles) {
            dtFile.writeBytesTo(buf);
        }
    }

    @Override
    public String toString() {
        // TODO 暂时这样
        return null;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        FileReadDireConAttachPack that = (FileReadDireConAttachPack) o;
        return direId == that.direId && fileNum == that.fileNum && fileReadDireConRD == that.fileReadDireConRD && followUpFlag == that.followUpFlag && Objects.equals(dtFiles, that.dtFiles);
    }

    @Override
    public int hashCode() {
        return Objects.hash(fileReadDireConRD, direId, followUpFlag, fileNum, dtFiles);
    }
}
